//
// Created by kenny on 25-10-27.
//
#include "mcp_retry_send.h"
#include "mcp_logger.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

// 定时线程
#ifdef _WIN32
static DWORD WINAPI timer_thread_func(LPVOID param);
#else
static void* timer_thread_func(void* param);
#endif

static retry_record_t* find_record(mcp_retry_manager_t* manager, uint16_t sequence);
static void remove_record(mcp_retry_manager_t* manager, int index);

/**
 * 初始化
 * @param manager
 * @param max_records  // 最大容量
 * @return
 */
int mcp_retry_manager_init(mcp_retry_manager_t* manager, int max_records) {
    if (!manager || max_records <= 0) {
        return -1;
    }

    memset(manager, 0, sizeof(mcp_retry_manager_t));
    manager->records = (retry_record_t*)malloc(sizeof(retry_record_t) * max_records);
    if (!manager->records) {
        return -1;
    }

    manager->max_records = max_records;
    manager->record_count = 0;
    manager->running = true;

    // 初始化锁
#ifdef _WIN32
    InitializeCriticalSection(&manager->lock);
#else
    pthread_mutex_init(&manager->lock, NULL);
#endif

    // 启动定时器线程
#ifdef _WIN32
    manager->timer_thread = CreateThread(NULL, 0, timer_thread_func, manager, 0, NULL);
    if (manager->timer_thread == NULL) {
        free(manager->records);
        return -1;
    }
#else
    if (pthread_create(&manager->timer_thread, NULL, timer_thread_func, manager) != 0) {
        free(manager->records);
        pthread_mutex_destroy(&manager->lock);
        return -1;
    }
#endif

    LOG_INFO("MCP Retry Manager -> initialized with %d max records", max_records);
    return 0;
}

/**
 * 释放资源
 * @param manager
 */
void mcp_retry_manager_cleanup(mcp_retry_manager_t* manager) {
    if (!manager) return;

    manager->running = false;

    // 等待定时器线程结束
#ifdef _WIN32
    if (manager->timer_thread) {
        WaitForSingleObject(manager->timer_thread, 3000);
        CloseHandle(manager->timer_thread);
    }
    DeleteCriticalSection(&manager->lock);
#else
    if (manager->timer_thread) {
        pthread_join(manager->timer_thread, NULL);
    }
    pthread_mutex_destroy(&manager->lock);
#endif

    // 清理所有记录
    for (int i = 0; i < manager->record_count; i++) {
        if (manager->records[i].packet_data) {
            free(manager->records[i].packet_data);
        }
    }

    free(manager->records);
    LOG_INFO("MCP Retry Manager -> cleaned up");
}

/**
 * 添加任务
 * @param manager
 * @param sequence 序号
 * @param packet_data  数据包
 * @param packet_length 数据包长度
 * @param timeout_callback  超时回调
 * @param success_callback  成功回调
 * @param user_data 用户数据
 * @return
 */
int mcp_retry_manager_add_message(mcp_retry_manager_t* manager,
                                  uint16_t sequence,
                                  const uint8_t* packet_data,
                                  uint16_t packet_length,
                                  void (*retry_callback)(uint16_t sequence, uint8_t* packet_data,uint16_t packet_length, void* user_data),
                                  void (*success_callback)(uint16_t sequence, void* user_data),
                                  void* user_data) {
    if (!manager || !packet_data || packet_length == 0) {
        return -1;
    }

#ifdef _WIN32
    EnterCriticalSection(&manager->lock);
#else
    pthread_mutex_lock(&manager->lock);
#endif

    // 检查是否已存在相同序列号的记录
    if (find_record(manager, sequence)) {
#ifdef _WIN32
        LeaveCriticalSection(&manager->lock);
#else
        pthread_mutex_unlock(&manager->lock);
#endif
        LOG_WARN("MCP Retry Manager -> Message with sequence %d already exists", sequence);
        return -1;
    }

    // 检查是否达到最大记录数
    if (manager->record_count >= manager->max_records) {
#ifdef _WIN32
        LeaveCriticalSection(&manager->lock);
#else
        pthread_mutex_unlock(&manager->lock);
#endif
        LOG_WARN("MCP Retry Manager -> Retry manager is full, cannot add new message");
        return -1;
    }

    // 添加新记录
    retry_record_t* record = &manager->records[manager->record_count];
    record->sequence = sequence;
    record->packet_data = (uint8_t*)malloc(packet_length);
    if (!record->packet_data) {
#ifdef _WIN32
        LeaveCriticalSection(&manager->lock);
#else
        pthread_mutex_unlock(&manager->lock);
#endif
        return -1;
    }
    // 这里是否需要深复制
    memcpy(record->packet_data, packet_data, packet_length);
    record->packet_length = packet_length;
    record->send_time = time(NULL);
    record->retry_count = 0;
    record->status = RETRY_PENDING;
    record->user_data = user_data;
    record->retry_callback = retry_callback;
    record->success_callback = success_callback;

    manager->record_count++;

#ifdef _WIN32
    LeaveCriticalSection(&manager->lock);
#else
    pthread_mutex_unlock(&manager->lock);
#endif

    LOG_DEBUG("Added message to retry manager: sequence=%d", sequence);
    return 0;
}

/**
 * 调用成功
 * @param manager
 * @param sequence
 * @return
 */
int mcp_retry_manager_handle_response(mcp_retry_manager_t* manager, uint16_t sequence) {
    if (!manager) return -1;

#ifdef _WIN32
    EnterCriticalSection(&manager->lock);
#else
    pthread_mutex_lock(&manager->lock);
#endif

    retry_record_t* record = find_record(manager, sequence);
    if (record) {
        // 调用成功回调
        if (record->success_callback) {
            record->success_callback(sequence, record->user_data);
        }

        // 移除记录
        for (int i = 0; i < manager->record_count; i++) {
            if (manager->records[i].sequence == sequence) {
                remove_record(manager, i);
                break;
            }
        }

        LOG_DEBUG("Response handled, removed message: sequence=%d", sequence);

#ifdef _WIN32
        LeaveCriticalSection(&manager->lock);
#else
        pthread_mutex_unlock(&manager->lock);
#endif
        return 0;
    }

#ifdef _WIN32
    LeaveCriticalSection(&manager->lock);
#else
    pthread_mutex_unlock(&manager->lock);
#endif

    LOG_DEBUG("No pending message found for response: sequence=%d", sequence);
    return -1;
}

/**
 * 移除指定记录
 * @param manager
 * @param sequence
 * @return
 */
int mcp_retry_manager_remove_message(mcp_retry_manager_t* manager, uint16_t sequence) {
    if (!manager) return -1;

#ifdef _WIN32
    EnterCriticalSection(&manager->lock);
#else
    pthread_mutex_lock(&manager->lock);
#endif

    for (int i = 0; i < manager->record_count; i++) {
        if (manager->records[i].sequence == sequence) {
            // LOG_DEBUG("<<<<<< Receive response 0x80: protocol=0x%02X, sequence=0x%04X", manager->records[i], sequence);
            remove_record(manager, i);

#ifdef _WIN32
            LeaveCriticalSection(&manager->lock);
#else
            pthread_mutex_unlock(&manager->lock);
#endif
           // LOG_DEBUG("Removed message from retry manager: sequence=%d", sequence);
            LOG_DEBUG("<<<<<< Receive response 0x80: sequence=0x%04X", sequence);
            return 0;
        }
    }

#ifdef _WIN32
    LeaveCriticalSection(&manager->lock);
#else
    pthread_mutex_unlock(&manager->lock);
#endif

    return -1;
}

/**
 * 设置回调函数
 * @param manager
 * @param on_no_response     全局回调，通知上级服务器还没有响应，再重发
 * @param on_message_timeout  全局回调，通知上级已经重发好几次了，超时未响应，判断为失败
 */
void mcp_retry_manager_set_callbacks(mcp_retry_manager_t* manager,
                                     void (*on_no_response)(uint16_t sequence, int retry_count),
                                     void (*on_message_timeout)(uint16_t sequence)) {
    if (!manager) return;

    manager->on_no_response = on_no_response;
    manager->on_message_timeout = on_message_timeout;
}


/**
 * 内部函数：查找记录
 * @param manager
 * @param sequence
 * @return
 */
static retry_record_t* find_record(mcp_retry_manager_t* manager, uint16_t sequence) {
    for (int i = 0; i < manager->record_count; i++) {
        if (manager->records[i].sequence == sequence) {
            return &manager->records[i];
        }
    }
    return NULL;
}

/**
 * 内部函数：移除记录
 * @param manager
 * @param index
 */
static void remove_record(mcp_retry_manager_t* manager, int index) {
    if (index < 0 || index >= manager->record_count) {
        return;
    }

    // 释放数据内存
    if (manager->records[index].packet_data) {
        free(manager->records[index].packet_data);
    }

    // 移动后续记录
    for (int i = index; i < manager->record_count - 1; i++) {
        manager->records[i] = manager->records[i + 1];
    }

    manager->record_count--;
}

/**
 * 定时器线程函数
 */
#ifdef _WIN32
static DWORD WINAPI timer_thread_func(LPVOID param) {
#else
static void* timer_thread_func(void* param) {
#endif
    mcp_retry_manager_t* manager = (mcp_retry_manager_t*)param;

    while (manager->running) {
        // 检查超时和重发
        mcp_retry_manager_check_timeouts(manager);

        // 每秒检查一次
#ifdef _WIN32
        Sleep(1000);
#else
        sleep(1);
#endif
    }

#ifdef _WIN32
    return 0;
#else
    return NULL;
#endif
}

/**
 * 检查是否时间到了要重发还是报异常
 * @param manager
 */
void mcp_retry_manager_check_timeouts(mcp_retry_manager_t* manager) {
    if (!manager) return;

#ifdef _WIN32
    EnterCriticalSection(&manager->lock);
#else
    pthread_mutex_lock(&manager->lock);
#endif

    time_t current_time = time(NULL);

    for (int i = 0; i < manager->record_count; i++) {
        retry_record_t* record = &manager->records[i];

        // 检查是否超时（3秒）
        if (current_time - record->send_time >= RETRY_INTERVAL_MS / 1000) {
            if (record->retry_count < MAX_RETRY_COUNT) {
                // 触发重发
                record->retry_count++;
                record->send_time = current_time;

                // 调用超时回调（用于重新发送消息）
                if (record->retry_callback) {
                    record->retry_callback(record->sequence, record->packet_data, record->packet_length,record->user_data);
                }

                LOG_DEBUG("Retry %d for message: sequence=%d", record->retry_count, record->sequence);

                // 全局回调，通知上级发送失败，还要重发
                if (manager->on_no_response) {
                    manager->on_no_response(record->sequence, record->retry_count);
                }
            } else {
                // 达到最大重试次数，移除消息
                LOG_WARN("Max retry count reached for message: sequence=%d", record->sequence);

                // 通知上层重试了几次失败了
                if (manager->on_message_timeout) {
                    manager->on_message_timeout(record->sequence);
                }

                remove_record(manager, i);
                i--; // 因为数组被移动了
            }
        }
    }

#ifdef _WIN32
    LeaveCriticalSection(&manager->lock);
#else
    pthread_mutex_unlock(&manager->lock);
#endif
}

